using System;
using System.Linq;
using Cmc.Modbus.Base;
using NewLife;
using NewLife.IP;
using NewLife.Log;
using NewLife.Net;
using ILog = NewLife.Log.ILog;

namespace Cmc.Modbus
{
    public class TcpServerClient : IClient, IDisposable
    {

        private NetUri uri;
        public ILog _log;
        private EventHandler<ReceivedEventArgs> _onReciveAsyncHandle;
        private readonly object lockRead = new object();

        private NetServer Server;
        private ISocketSession client;

        public TcpServerClient(string ip, int port, NetServer netServer, EventHandler<ReceivedEventArgs> onReciveAsyncHandle = null, ILog log = null)
        {
            IP = ip;
            Port = port;
            _onReciveAsyncHandle = onReciveAsyncHandle;
            uri = new NetUri(NetType.Tcp, IP, Port);
            _log = log ?? XTrace.Log;
            Server = netServer;
        }


        private ReceivedEventArgs lastData;
        private DateTime lastDateTime;

        private void Client_Received(object sender, ReceivedEventArgs e)
        {
            lastData = e;
            lastDateTime = DateTime.Now;
            try
            {
                byte[] bytes = e.Packet.ReadBytes(0, e.Packet.Count);

                _log.Info($"{client.Remote.Address}:{client.Remote.Port}接收数据{bytes.ToHex(" ")}");

                if (_onReciveAsyncHandle != null)
                {
                    e.Packet = bytes;
                    _onReciveAsyncHandle(sender, e);
                }
            }
            catch (Exception exception)
            {
                client.Log.Warn(exception.ToString());
            }
        }

        ISocketSession GetSession()
        {
            var temp = Server.Sessions.Values.Select(m => m.Session).FirstOrDefault(m => m.Remote.Address.ToString() == IP && m.Remote.Port == Port);
            if ((temp != null && client == null) || (temp != null && client != null && temp.ID != client.ID))
            {
                temp.Received += Temp_Received;
            }
            return temp;
        }

        private void Temp_Received(object sender, ReceivedEventArgs e)
        {
            Client_Received(sender, e);
        }

        public override bool SendBytes(byte[] bytes)
        {
            if (TryConnect())
            {
                var result = client.Send(bytes);
                if (result == bytes.Length)
                {
                    return true;
                }
            }
            return false;
        }

        public override byte[] RecieveBytes()
        {
            var packet = client.Receive();
            return packet.ReadBytes(0, packet.Count);
        }

        bool TryConnect()
        {
            client = GetSession();
            if (client == null)
            {
                IsConnected = false;
                _log.Warn($"位于网络地址的[{IP}:{Port}]TCP通讯未连接！");
                return false;
            }
            return IsConnected;
        }

        public override byte[] RecieveBytes(byte[] sendBytes)
        {
            lock (lockRead)
            {
                if (TryConnect())
                {
                    var result = client.Send(sendBytes);
                    DateTime dtFlag = DateTime.Now;
                    if (result == sendBytes.Length)
                    {
                        //var packet = client.Receive();  //newlift框架问题，第一次数据不能同步读取
                        //return packet.ReadBytes(0, packet.Count);
                        while (dtFlag.AddMilliseconds(1000) > DateTime.Now) //1秒内等待异步读取
                        {
                            if (lastDateTime > dtFlag)
                            {
                                var packet = lastData.Packet;
                                return packet.ReadBytes(0, packet.Count);
                            }
                        }
                    }
                }
            }
            return null;
        }
         public void Dispose()
        {
            client?.Dispose();
        }
    }
}
